package com.example.nettyrpcdemo.core;

import com.google.protobuf.CodedInputStream;
import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;
import tools.MessageManager;

@Slf4j
public class Decoder extends LengthFieldBasedFrameDecoder {

    // 64K?
    public static final int MAX_LEN = 64 * 1024;

    public Decoder() {
        super(Integer.MAX_VALUE,                      // 最大程度不限
                0, 4,    // 4位为长度头(其实就是取出这么多个字节后，就是一个完整长度包了)
                -4,                    // 由于总长度包含头长度，所以需要进行修正
                0);                    // 不跳过任何字节（比如头长度），客户端发什么就接什么
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
        ByteBuf buffs = (ByteBuf) super.decode(ctx, buf);
        if (buffs == null) {
            return null;
        }

        // step1:header4
        int len = buffs.readInt();

        // step2:msgId4
        int msgId = buffs.readInt();

        if (len > MAX_LEN) {
            return null;
        }

        // step3:序列号8
        long seqId = buffs.readLong();

        // 真正的body
        Message.Builder msgBuilder = MessageManager.getBuilderByMsgCode(msgId);
        if (msgBuilder == null) {
            log.error("无法识别的消息, msgId = {}", msgId);
            return null;
        }

        try {
            // // step4:剩余的字节是body
            byte[] msgBody = new byte[buffs.readableBytes()];
            buffs.readBytes(msgBody);

            msgBuilder.clear();
            msgBuilder.mergeFrom(msgBody);

            GeneratedMessage newMsg = (GeneratedMessage) msgBuilder.build();

            return new ProtobufMessage(seqId, msgId, newMsg);
        } catch (Exception e) {
            log.error("error=", e);
        } finally {
            buffs.release();
        }
        return null;
    }
}
